package com.ls.lspicturebackend.aop;

import cn.hutool.core.util.ObjUtil;
import com.ls.lspicturebackend.annotation.PictureAuthCheck;
import com.ls.lspicturebackend.common.DeleteRequest;
import com.ls.lspicturebackend.constant.UserConstant;
import com.ls.lspicturebackend.exception.BusinessException;
import com.ls.lspicturebackend.exception.ErrorCode;
import com.ls.lspicturebackend.model.dto.picture.CreatePictureOutPaintingTaskRequest;
import com.ls.lspicturebackend.model.dto.picture.PictureObjRequest;
import com.ls.lspicturebackend.model.entity.Picture;
import com.ls.lspicturebackend.model.entity.Space;
import com.ls.lspicturebackend.model.entity.SpaceUser;
import com.ls.lspicturebackend.model.entity.User;
import com.ls.lspicturebackend.model.enums.SpaceRoleEnum;
import com.ls.lspicturebackend.model.enums.SpaceTypeEnum;
import com.ls.lspicturebackend.service.PictureService;
import com.ls.lspicturebackend.service.SpaceService;
import com.ls.lspicturebackend.service.SpaceUserService;
import com.ls.lspicturebackend.service.UserService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

@Aspect
@Component
public class PictureAuthInterceptor {

    @Resource
    private UserService userService;

    @Resource
    private PictureService pictureService;

    @Resource
    private SpaceService spaceService;

    @Resource
    private SpaceUserService spaceUserService;

    @Around("@annotation(pictureAuthCheck)")
    public Object doInterceptor(ProceedingJoinPoint joinPoint, PictureAuthCheck pictureAuthCheck) throws Throwable {
        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        User loginUser = userService.getLoginUser(request);
        // 如果是整个系统的管理员，开放所有权限
        if (UserConstant.ADMIN_ROLE.equals(loginUser.getUserRole())) {
            return joinPoint.proceed();
        }
        Object argObj = joinPoint.getArgs()[0];
        PictureObjRequest arg = new PictureObjRequest();
        if (argObj instanceof CreatePictureOutPaintingTaskRequest) {
            arg.setId(((CreatePictureOutPaintingTaskRequest) argObj).getPictureId());
        } else if (argObj instanceof PictureObjRequest) {
            arg = (PictureObjRequest) argObj;
        } else if (argObj instanceof DeleteRequest) {
            arg.setId(((DeleteRequest) argObj).getId());
        }
        // 图片id为空，即是上传或者删除图片
        // 如果图片id和空间id为空则说明向公共图库上传图片
        Long pictureId = arg.getId();
        Long spaceId = arg.getSpaceId();
        if (ObjUtil.isAllEmpty(pictureId, spaceId)) {
            return joinPoint.proceed();
        }
        // 如果图片id为空，空间id不为空则说明向个人或团队图库上传图片
        if (ObjUtil.isEmpty(pictureId) && ObjUtil.isNotEmpty(spaceId)) {
            Space space = spaceService.getById(spaceId);
            SpaceTypeEnum spaceTypeEnum = getSpaceType(space);
            // 个人图库
            if (SpaceTypeEnum.PRIVATE.equals(spaceTypeEnum)) {
                if (!loginUser.getId().equals(space.getUserId())) {
                    throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "没有权限");
                }
                return joinPoint.proceed();
            }
            // 团队图库
            if (SpaceTypeEnum.TEAM.equals(spaceTypeEnum)) {
                checkSpaceAuth(spaceId, loginUser.getId());
                return joinPoint.proceed();
            }
        }
        // 修改或删除图片
        // 如果图片id不为空，但是空间为空
        // 说明修改公共图库的图片，或删除图片所在图库的图片
        // 使用ai扩图修改图片
        if (ObjUtil.isNotEmpty(pictureId) && ObjUtil.isEmpty(spaceId)) {
            Picture picture = pictureService.getById(pictureId);
            // 修改和删除公共图库的图片
            if (ObjUtil.isEmpty(picture.getSpaceId())) {
                if (!loginUser.getId().equals(picture.getUserId())) {
                    throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "没有权限");
                }
                return joinPoint.proceed();
            }
            // 删除个人或团队图库的图片
            Space space = spaceService.getById(picture.getSpaceId());
            if (ObjUtil.isEmpty(space)) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "图库不存在");
            }
            SpaceTypeEnum enumByValue = SpaceTypeEnum.getEnumByValue(space.getSpaceType());
            // 删除个人图库的图片
            if (SpaceTypeEnum.PRIVATE.equals(enumByValue)) {
                if (!loginUser.getId().equals(space.getUserId()) ||
                        !loginUser.getId().equals(picture.getUserId())) {
                    throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "没有权限");
                }
                return joinPoint.proceed();
            }
            // 删除团队图库的图片
            if (SpaceTypeEnum.TEAM.equals(enumByValue)) {
                checkSpaceAuth(space.getId(), loginUser.getId());
                return joinPoint.proceed();
            }
        }
        // 如果图片id和空间id不为空，说明修改个人或团队图库的图片
        if (ObjUtil.isAllNotEmpty(pictureId, spaceId)) {
            Space space = spaceService.getById(spaceId);
            SpaceTypeEnum spaceType = getSpaceType(space);
            Picture picture = pictureService.getById(pictureId);
            if (ObjUtil.isEmpty(picture)) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "图片不存在");
            }
            // 修改个人图库图片
            if (SpaceTypeEnum.PRIVATE.equals(spaceType)) {
                if (!loginUser.getId().equals(space.getUserId())) {
                    throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "没有权限");
                }
                if (!loginUser.getId().equals(picture.getUserId())) {
                    throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "没有权限");
                }
                if (!picture.getSpaceId().equals(spaceId)) {
                    throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "没有权限");
                }
                return joinPoint.proceed();
            }
            // 修改团队图库图片
            if (SpaceTypeEnum.TEAM.equals(spaceType)) {
                if (!picture.getSpaceId().equals(spaceId)) {
                    throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "没有权限");
                }
                checkSpaceAuth(spaceId, loginUser.getId());
                return joinPoint.proceed();
            }
        }
        throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "没有权限");
    }

    private SpaceTypeEnum getSpaceType(Space space) {
        if (ObjUtil.isEmpty(space)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        SpaceTypeEnum spaceTypeEnum = SpaceTypeEnum.getEnumByValue(space.getSpaceType());
        if (ObjUtil.isEmpty(spaceTypeEnum)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        return spaceTypeEnum;
    }

    private void checkSpaceAuth(Long spaceId, Long userId) {
        String spaceRole = spaceUserService.lambdaQuery()
                .select(SpaceUser::getSpaceRole)
                .eq(SpaceUser::getUserId, userId)
                .eq(SpaceUser::getSpaceId, spaceId)
                .oneOpt()
                .map(SpaceUser::getSpaceRole)
                .orElse(null);
        if (ObjUtil.isEmpty(spaceRole) || SpaceRoleEnum.VIEWER.equals(SpaceRoleEnum.getEnumByValue(spaceRole))) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "没有权限");
        }
    }
}
